import os
import binascii

dirname, filename = os.path.split(os.path.abspath(__file__)) 
# os.path.realpath(__file__)

INDEXES_LENGTH = int(1024 * 1024 / 2)

SAVE_DB_PATH = os.path.join(dirname, 'db_data')
SAVE_INODE_NAME_SUFFIX = '.db'
SAVE_INDEXES_NAME_SUFFIX = '.indeses'

DEFAULT_ID = '00000000000000000000000000000000'

class OSDB:
    def __init__(self, dbname):
        if os.path.exists(SAVE_DB_PATH) == False:
            os.makedirs(SAVE_DB_PATH)

        self.dbname = dbname
        self.dataPath = os.path.join(SAVE_DB_PATH, dbname + SAVE_INODE_NAME_SUFFIX)
        self.indexesPath = os.path.join(SAVE_DB_PATH, dbname + SAVE_INDEXES_NAME_SUFFIX)

        if os.path.exists(self.dataPath) == False:
            fd = open(self.indexesPath, mode="wb")
            for i in range(INDEXES_LENGTH):
                fd.write(binascii.a2b_hex(DEFAULT_ID))
                fd.write(int(1).to_bytes(length=4, byteorder='big'))
            fd.close()

    def __getDataOffset(self, index):
        fd = open(self.indexesPath, mode="rb")
        fd.seek(index * 20, 0)
        idBinary = fd.read(16)
        offsetBinary = fd.read(4)
        fd.close()

        id = binascii.b2a_hex(idBinary).decode()
        offset = int.from_bytes(offsetBinary, byteorder='big')
        return id, offset

    def __putDataOffset(self, index, id, offset):
        fd = open(self.indexesPath, mode="rb+")
        fd.seek(index * 20, 0)
        fd.write(binascii.a2b_hex(id))
        fd.seek(index * 20 + 16, 0)
        fd.write(int(offset).to_bytes(length=4, byteorder='big'))
        fd.close()

    def __hash(self, id):
        return int(id, 16) % INDEXES_LENGTH

    def add(self, id, inodeInfo):
        index = self.__hash(id)
        oid, offset = self.__getDataOffset(index)
        if id == oid:
            print('记录已存在')
        elif DEFAULT_ID == oid:
            fd = open(self.dataPath, mode="ab")
            offset = fd.tell()

            inodeInfoArr = inodeInfo.split('\n')
            for inodeLine in inodeInfoArr:
                fd.write(bytes(inodeLine + '\n', encoding='utf8'))

            fd.write(binascii.a2b_hex('ED') + b'\n')

            fd.close()

            self.__putDataOffset(index, id, offset)
        else:
            print('哈希冲突')

    def get(self, id):
        index = self.__hash(id)
        oid, offset = self.__getDataOffset(index)

        result = []

        fd = open(self.dataPath, mode="rb")
        fd.seek(offset, 0)
        while True:
            line = fd.readline()
            if line == b'\xed\n':
                break
            else:
                result.append(line[:-1])
        fd.close()

        return result
